package de.dhbw.karlsruhe.picsim.model.memory.impl;

import de.dhbw.karlsruhe.picsim.model.memory.CommandRegisterAddress;
import de.dhbw.karlsruhe.picsim.model.memory.DirectAddressAbleStack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 12, 2010
 * Time: 3:26:25 PM
 */
public final class StackFacadeImpl implements DirectAddressAbleStack {
    private static final Log log = LogFactory.getLog(StackFacadeImpl.class);
    public static final int HIGHEST_STACK_NUMBER = 7;
    private final Map<Integer, CommandRegisterAddress> addresses;
    private int pointer;

    public StackFacadeImpl() {
        addresses = new HashMap<Integer, CommandRegisterAddress>(HIGHEST_STACK_NUMBER + 1);
        pointer = 0;
    }

    @Override
    public int getPointer() {
        return pointer;
    }

    @Override
    @NotNull
    public CommandRegisterAddress getAddress(final int where) {
        if (where < 0 || where > HIGHEST_STACK_NUMBER) {
            throw new IllegalArgumentException(String.valueOf(where));
        }
        final CommandRegisterAddress normalResult = addresses.get(where);
        if (normalResult != null) {
            return normalResult;
        } else {
            //greift das Gui drauf zu.. solang noch nichts besseres gibt geben wir einfach mal 0 zurück
            return CommandRegisterAddressImpl.createUnSafe(0);

        }
    }

    @Override
    public void setAddress(final int where, @NotNull final CommandRegisterAddress address) {
        if (where < 0 || where > HIGHEST_STACK_NUMBER) {
            throw new IllegalArgumentException(String.valueOf(where));
        }
        addresses.put(where, address);


    }

    @Override
    public void pushAddress(@NotNull final CommandRegisterAddress address) {
        log.info(address + "was pushed to stack");
        addresses.put(pointer, address);

        if (pointer < HIGHEST_STACK_NUMBER) {
            pointer++;
        } else {
            pointer = 0;
        }
    }

    @NotNull
    @Override
    public CommandRegisterAddress popAddress() {
        if (pointer > 0) {
            pointer--;
        } else {
            pointer = HIGHEST_STACK_NUMBER;
        }

        CommandRegisterAddress result;
        result = addresses.get(pointer);
        if (result != null) {
            addresses.remove(pointer);
            log.info("return " + result + " from stack");
        } else {
            log.warn("Access to uninitialized Stack : Set to Zero");

            result = CommandRegisterAddressImpl.createUnSafe(0);
        }
        return result;
    }
}
